#define OFFSET 0x600

#include "typedef.h"
#include "arm_common.h"

typedef struct Watchdog
{
    /**
     * @brief Private Timer Load Register
     * @note The Timer Load Register contains the value copied to 
     * the Timer Counter Register when it decrements down to zero
     * with auto reload mode enabled. Writing to the Timer Load 
     * Register means that you also write to the Timer Counter Register.
     */
    word pt_load;

    /**
     * @brief Private Timer Counter Register
     * @note The Timer Counter Register is a decrementing counter.
     * @note If a Cortex-A9 processor timer is in debug state, 
     * @note the counter only decrements when the Cortex-A9 processor returns to non-debug state.
     */
    word pt_counter;

    /**
     * @brief Private Timer Control Register
     * @note bit0 Timer enable
     * @note bit1 Auto reload
     * @note bit2 IRQ enable
     * @note bit15-bit8 Prescaler
     */
    word pt_control;

    /**
     * @brief Private Timer Interrupt Status
     * @note Interrupt ID 29 is set as pending in the Interrupt Distributor
     * after the event flag is set. The event flag is cleared when written to 1.
     */
    word int_status;

    word wd_load;
    word wd_counter;
    word wd_int_status;
    word wd_reset_status;
} *Watchdog;

static Watchdog wdog;

void private_timer_init()
{
    address base = get_pheriphal_addr();
    wdog = CAST_AS(Watchdog, base + OFFSET);
}

/**
 * @brief Set the private timer period object
 *
 * @param n must under 32 bits
 * @param m must under 8 bits
 * @note generate an int with freqency as (n/m) times reference clock
 * @note reference clock is the core pheriphal clock
 */
void set_private_timer_period(unsigned int n, unsigned char m)
{
    wdog->pt_control = 0;
    wdog->int_status = 1;
    wdog->pt_load = n;
    wdog->pt_control = (m << 8) | 0b111;
}

void clean_private_timer_int_status()
{
    wdog->int_status = 1;
}